%{
	open Ast
%}

%token EOF LPAR RPAR LBRA RBRA PLUS MINUS TIMES DIV MOD LT LE GT GE EQUALS NOTEQUALS NOT AND OR CLASS EXTENDS TRUE FALSE IF ELSE IN INSTANCEOF NEW NULL STATIC THIS ASSIGN COMMA SEMICOLON POINT
%token <int> INT
%token <string> STRING
%token <string> VARIDENT
%token <string> CLASSIDENT

%start file
%type <Ast.file_elements> file

%left OR
%left AND
%left LT LE GT GE EQUALS NOTEQUALS
%left PLUS MINUS
%left TIMES DIV MOD
%right UMINUS UPLUS
%right CAST
%right UNOT
%%

file:
| EOF { Empty }
| classe_ou_expr file { FileElements($1, $2) }
;
classe_ou_expr:
| classe { $1 }
| expr { MainExpr($1) }
;
classe:
| CLASS CLASSIDENT attributs_ou_methodes_ou_rien { Classdef($2, "Object", $3)}
| CLASS CLASSIDENT EXTENDS CLASSIDENT attributs_ou_methodes_ou_rien { Classdef($2, $4, $5)}
;
attributs_ou_methodes_ou_rien:
| LBRA RBRA { Nodeclaration }
| LBRA attributs_ou_methodes RBRA { $2 }
;
attributs_ou_methodes:
| attribut_ou_methode { Classdecl($1, false, Nodeclaration) }
| attribut_ou_methode attributs_ou_methodes { Classdecl($1, false, $2) }
| STATIC attribut_ou_methode { Classdecl($2, true, Nodeclaration) }
| STATIC attribut_ou_methode attributs_ou_methodes { Classdecl($2, true, $3) }
;
attribut_ou_methode:
| attribut SEMICOLON { $1 }
| methode { $1 }
;
attribut:
| CLASSIDENT VARIDENT { Attributedef($1, $2, Null) }
| CLASSIDENT VARIDENT ASSIGN expr { Attributedef($1, $2, $4) }
;
methode:
| CLASSIDENT VARIDENT params_ou_rien exprs_ou_rien { Methodedef($1, $2, $3, $4) }
;
params_ou_rien:
| LPAR RPAR { NoParam }
| LPAR params RPAR { $2 }
;
params:
| param { Params($1, NoParam) }
| param COMMA params { Params($1, $3) }
;
param:
| CLASSIDENT VARIDENT { Param($1, $2) }
;
args_ou_rien:
| LPAR RPAR { NoArg }
| LPAR args RPAR { $2 }
;
args:
| expr { Args($1, NoArg) }
| expr COMMA args { Args($1, $3) }
;
exprs_ou_rien:
| LBRA RBRA { NoExpression }
| LBRA exprs RBRA { $2 }
;
exprs:
| expr { $1 }
| expr SEMICOLON { $1 }
| expr SEMICOLON exprs { Binop(Bsemicolon, $1, $3) }
;
expr:
| exprs_ou_rien { $1 }
| LPAR expr RPAR { $2 }
| MINUS expr %prec UMINUS { Unop(Uminus,$2)}
| PLUS expr %prec UPLUS { Unop(Uplus,$2)}
| NOT expr %prec UNOT { Unop(Unot,$2)}
| expr OR expr { Binop(Bor,$1,$3) }
| expr AND expr { Binop(Band,$1,$3) }
| expr LT expr { Binop(Blt,$1,$3) }
| expr LE expr { Binop(Ble,$1,$3) }
| expr GT expr { Binop(Bgt,$1,$3) }
| expr GE expr { Binop(Bge,$1,$3) }
| expr EQUALS expr { Binop(Bequals,$1,$3) }
| expr NOTEQUALS expr { Binop(Bnotequals,$1,$3) }
| expr MINUS expr { Binop(Bsub,$1,$3) }
| expr PLUS expr { Binop(Badd,$1,$3) }
| expr TIMES expr { Binop(Bmul,$1,$3) }
| expr DIV expr { Binop(Bdiv,$1,$3) }
| expr MOD expr { Binop(Bmod,$1,$3) }
| VARIDENT ASSIGN expr { Set(Var($1), $3) }
| expr POINT VARIDENT ASSIGN expr { Set(Get($1, $3), $5) }
| expr POINT VARIDENT { Get($1, $3) }
| expr POINT VARIDENT args_ou_rien { Call($1, $3, $4) }
| CLASSIDENT VARIDENT ASSIGN expr IN expr { Declare($1, $2, $4, $6) }
| IF LPAR expr RPAR expr ELSE expr { If($3, $5, $7) }
| IF LPAR expr RPAR expr { If($3, $5, NoExpression) }
| LPAR CLASSIDENT RPAR expr %prec CAST { Cast($2, $4) }
| NEW CLASSIDENT { New($2) }
| expr INSTANCEOF CLASSIDENT { Instanceof($1, $3) }
| VARIDENT { Var($1) }
| CLASSIDENT { Class($1) }
| const { $1 }
| THIS { Var("this") }
;
const:
| INT { Constint($1) }
| STRING { Conststring($1) }
| TRUE { Constbool(true) }
| FALSE { Constbool(false) }
| NULL { Null }
%%